using System.Collections.Generic;
using System.Collections.ObjectModel;
using MvpFramework.Specifications;


namespace MvpFramework.Infastructure
{
    /// <summary>
    /// Manages validation for Views
    /// </summary>
    public class SpecificationManager
    {
        private readonly SpecificationFactory _factory;

        /// <summary>
        /// Default Constructor.
        /// </summary>
        public SpecificationManager()
            : this(new SpecificationFactory())
        {
        }

        internal SpecificationManager(SpecificationFactory factory)
        {
            _factory = factory;
        }
        /// <summary>
        /// Returns all failed specs for the view
        /// </summary>
        /// <param name="view"></param>
        /// <returns></returns>
        public ReadOnlyCollection<Specification<T>> GetFailedSpecifications<T>(T view) where T:IMvpView
        {
            var allSpecs = _factory.GetSpecificationsFor<T>();
            var failedSpecs = new List<Specification<T>>(allSpecs.Count);
            foreach (Specification<T> spec in allSpecs)
            {
                if (!spec.IsSatisfiedBy(view))
                {
                    failedSpecs.Add(spec);
                }
            }
            return new ReadOnlyCollection<Specification<T>>(failedSpecs);
        }
        /// <summary>
        /// Returns all passed specs for the view
        /// </summary>
        /// <param name="view"></param>
        /// <returns></returns>
        public ReadOnlyCollection<Specification<T>> GetPassedSpecifications<T>(T view)
        {
            var allSpecs = new List<Specification<T>>(_factory.GetSpecificationsFor<T>());
            
            var failedSpecs = new List<Specification<T>>(allSpecs.Count);
            foreach (var spec in allSpecs)
            {
                if (!spec.IsSatisfiedBy(view))
                {
                    failedSpecs.Add(spec);
                }
            }
            return new ReadOnlyCollection<Specification<T>>(allSpecs.FindAll(spec => !failedSpecs.Contains(spec)));
        }
    }
}